package com.yang.train.member.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.yang.train.common.exception.BusinessException;
import com.yang.train.common.exception.BusinessExceptionEnum;
import com.yang.train.common.util.JwtUtil;
import com.yang.train.common.util.SnowUtil;
import com.yang.train.member.domain.Member;
import com.yang.train.member.domain.MemberExample;
import com.yang.train.member.domain.SmsRecords;
import com.yang.train.member.domain.SmsRecordsExample;
import com.yang.train.member.mapper.MemberMapper;
import com.yang.train.member.mapper.SmsRecordsMapper;
import com.yang.train.member.req.MemberLoginReq;
import com.yang.train.member.req.MemberRegisterReq;
import com.yang.train.member.req.MemberSendCodeReq;
import com.yang.train.member.resp.MemberLoginResp;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class MemberService {
    private static final Logger LOG = LoggerFactory.getLogger(MemberService.class);
    @Resource
    private MemberMapper memberMapper;

    @Resource
    private SmsRecordsMapper smsRecordsMapper;
    public Long count() {
     return memberMapper.countByExample(null);
    }
    public long register(MemberRegisterReq req){
        String mobile=req.getMobile();
        MemberExample memberExample = new MemberExample();
        memberExample.createCriteria().andMobileEqualTo(mobile);
        List<Member> list = memberMapper.selectByExample(memberExample);
        if (CollUtil.isNotEmpty(list)){
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_EXIST);
        }

        Member member = new Member();
        member.setId(SnowUtil.getSnowflakeNextId());
        member.setMobile(mobile);
        memberMapper.insert(member);
        return member.getId();
    }
    public String sendCode(MemberSendCodeReq req){
        String mobile=req.getMobile();
        Member memberDB  = selectByMobile(mobile);
        //用户表处理
        // 如果手机号不存在，则在用户表中插入一条记录
        if (ObjectUtil.isNull(memberDB)) {
            LOG.info("手机号不存在，插入一条记录");
            Member member = new Member();
            member.setId(SnowUtil.getSnowflakeNextId());
            member.setMobile(mobile);
            memberMapper.insert(member);
        } else {
            LOG.info("手机号存在，不插入记录");
        }

        //短信表处理 如果三分钟内无验证消息，则生成，否则返回三分钟内已经存在未验证的验证信息
        SmsRecordsExample example = new SmsRecordsExample();
        example.createCriteria().andPhoneNumberEqualTo(mobile)
                .andIsUsedEqualTo(false)
                .andSendTimeLessThanOrEqualTo(DateTime.now())
                .andExpiryDateGreaterThanOrEqualTo(DateTime.now());
        example.setOrderByClause("send_time");
        List<SmsRecords> smsRecords = smsRecordsMapper.selectByExample(example);
        //验证码（提升作用域）
        String code;
        if (smsRecords.isEmpty()){
            //生成验证码
            code = RandomUtil.randomNumbers(6);
            LOG.info("生成短信验证码：{}", code);
            //保存短信记录表：手机号、短信验证码、有效期，是否已使用、业务类型，发送时间、使用时间
            LOG.info("保存短信记录表");
            SmsRecords record = new SmsRecords();
            DateTime sendTime = DateTime.now();
            record.setId(SnowUtil.getSnowflakeNextId());
            record.setPhoneNumber(mobile);
            record.setExpiryDate(DateUtil.offsetMinute(sendTime,3));
            record.setIsUsed(false);
            record.setBusinessType("登录/注册");
            record.setSmsCode(code);
            record.setSendTime(sendTime);
            smsRecordsMapper.insert(record);
        }else {
            code = smsRecords.get(0).getSmsCode();
            LOG.info("短信验证码已存在：{}", code);
        }

        //对接短信通道，发送短信（解释短信验证码）
        LOG.info("对接短信通道，发送短信验证码{}",code);
        return code;
    }
    public MemberLoginResp login(MemberLoginReq req) {
        String mobile = req.getMobile();
        String code = req.getCode();
        Member memberDB = selectByMobile(mobile);

        // 如果手机号不存在，则插入一条记录
        if (ObjectUtil.isNull(memberDB)) {
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_NOT_EXIST);
        }

        // 校验短信验证码
        SmsRecordsExample example = new SmsRecordsExample();
        example.createCriteria().andPhoneNumberEqualTo(mobile)
                .andIsUsedEqualTo(false)
                .andSendTimeLessThanOrEqualTo(DateTime.now())
                .andExpiryDateGreaterThanOrEqualTo(DateTime.now());
        example.setOrderByClause("send_time");
        List<SmsRecords> smsRecords = smsRecordsMapper.selectByExample(example);
        if (smsRecords.isEmpty()){
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_NOT_EXIST);
        }
        String smsCode = smsRecords.get(0).getSmsCode();
        if (!smsCode.equals(code)) {
            throw new BusinessException(BusinessExceptionEnum.MEMBER_MOBILE_CODE_ERROR);
        }else{
            Long id = smsRecords.get(0).getId();
            //查询条件
            SmsRecordsExample recordsExample = new SmsRecordsExample();
            recordsExample.createCriteria().andIdEqualTo(id);
            //更新内容
            SmsRecords record = new SmsRecords();
            record.setIsUsed(true);
            record.setUseTime(DateTime.now());
            //更新数据库
            smsRecordsMapper.updateByExampleSelective(record,recordsExample);
        }
        //封装返回结果和token
        MemberLoginResp memberLoginResp = BeanUtil.copyProperties(memberDB, MemberLoginResp.class);
        String token = JwtUtil.createToken(memberLoginResp.getId(), memberLoginResp.getMobile());
        memberLoginResp.setToken(token);

        return memberLoginResp;
    }
    //根据手机号查询记录
    private Member selectByMobile(String mobile) {
        MemberExample memberExample = new MemberExample();
        memberExample.createCriteria().andMobileEqualTo(mobile);
        List<Member> list = memberMapper.selectByExample(memberExample);
        if (CollUtil.isEmpty(list)) {
            return null;
        } else {
            return list.get(0);
        }
    }
}
